using System;
using System.Collections.Generic;
using Sce.PlayStation.Core;

namespace Nyanimals
{
	public class CBlender
	{
		private float transitionTime;
		private float currentTime;	
		private CInterpolator interpolator;
		private tFrameLimit curLimit;
		private tFrameLimit nextLimit;
		
		List<Matrix4> NextTranBones;
		List<Matrix4> NextUntransBones;
		
		private bool filledLists = false;
	
		private bool stillBlending;
		
		public float TransitionTime
		{
			get { return transitionTime;}
			set { transitionTime = value;}
		}
		public float CurrentTime
		{
			get { return currentTime;}
			set { currentTime = value;}
		}
		public tFrameLimit CurrentLimit
		{
			get { return curLimit;}
			set { curLimit = value;}
		}
		public tFrameLimit NextLimit
		{
			get { return nextLimit;}
			set { nextLimit = value;}
		}
		public bool StillBlending
		{
			get { return stillBlending;}
			set { stillBlending = value;}
		}
		public float GetDissolveFactor()
		{
			return transitionTime/currentTime;
		}
	
		public void Setup(ref CInterpolator Interp, ref tFrameLimit curLimit, ref tFrameLimit nextLimit, float fTransitionTime)
		{
			currentTime = 0.0f;
			transitionTime = fTransitionTime;
			this.curLimit = curLimit;
			this.nextLimit = nextLimit;
			this.interpolator = Interp;
			stillBlending = true;
			
			CAnimation anim = CAnimationManager.Instance.GetAnimation(Interp.AnimationIndex);
			if(filledLists == false || anim.Bones.Count != NextTranBones.Count)
			{
				// get the joints for the next animation's 1st frame
				NextTranBones = new List<Matrix4>(anim.Bones.Count);
				NextUntransBones = new List<Matrix4>(anim.Bones.Count);
				
				Matrix4 identity = Matrix4.Identity;
				// fill the two lists to give them a size
				for(int i = 0; i < anim.Bones.Count; ++i)
				{
					NextTranBones.Add(identity);
					NextUntransBones.Add(identity);
				}
				filledLists = true;
			}
		}
	
		public void Dissolve(ref List<Matrix4> tranBones, ref List<Matrix4> untransBones, float fTime, ref Matrix4 pParentMat)
		{
			currentTime += fTime;
			float lamda = currentTime / transitionTime;
			
			// cap lamda at 100%
			if(lamda > 1.0f)
			{
				lamda = 1.0f;
				stillBlending = false;
				//Console.WriteLine("Blending done");
			}
			
			CAnimation anim = CAnimationManager.Instance.GetAnimation(interpolator.AnimationIndex);
			try
			{
				interpolator.Time += fTime;
				interpolator.Process(tranBones, untransBones, curLimit, pParentMat);
				float cacheInterpTime = interpolator.Time;
				
				interpolator.Time = anim.Bones[0].KeyFrames[nextLimit.StartFrame].KeyTime;
				interpolator.Process(NextTranBones, NextUntransBones, nextLimit, pParentMat);
				interpolator.Time = cacheInterpTime;
			}
			catch
			{
				Console.WriteLine("blend catch");
				stillBlending = false;
				tranBones = NextTranBones;
				untransBones = NextUntransBones;
			}
			
			// interpolate them
			for(int boneIndex = 0; boneIndex < tranBones.Count; ++boneIndex)
			{
				// the interpolates untransformed bones
				Matrix4 curBone = untransBones[boneIndex];
				Matrix4 nextBone = NextUntransBones[boneIndex];
				untransBones[boneIndex] = CMath.Interpolate(curBone, nextBone, lamda);
				
				// the transformed bone calculation
				tranBones[boneIndex] = untransBones[boneIndex] * anim.BindPoseInverse[boneIndex];
				
			}
					
		}
	
	}
}

